
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "symtab.h"
#include "expression.h"

struct symbol* create_symbol(const char* name)
{
    struct symbol* res = (struct symbol*)malloc(sizeof(struct symbol));
    res->name = (char*)malloc(strlen(name) + 1);
    strcpy(res->name, name);
    return res;
}

struct symbol* create_expression_symbol(const char* nm, struct expression* vl)
{
    struct symbol* res = create_symbol(nm);
    res->value.expr = vl;
    return res;
}

struct symbol* create_lambda_symbol(const char* nm, struct lambda* fn)
{
    struct symbol* res = create_symbol(nm);
    res->value.func = fn;
    return res;
} 

void destroy_symbol(struct symbol* sym)
{
    free(sym->name);
    free(sym->value.expr);
    free(sym);
}

struct symbol_table* create_symbol_table()
{
    struct symbol_table* res = (struct symbol_table*)malloc(sizeof(struct symbol_table));
    res->begin = NULL;
    res->end = NULL;
    res->count = 0;
    return res;
}

void insert_symbol(struct symbol_table* table, struct symbol* sym)
{
    if( table->begin == NULL && table->end == NULL ) {
        table->begin = sym;
        table->end = table->begin;
        table->end->link = NULL;
    }
    else {
        table->end->link = sym;
        table->end = sym;
        table->end->link = NULL;
    }
    ++table->count;
}

struct symbol* search_symbol(struct symbol_table* table, const char* name)
{
    struct symbol* p = table->begin;
    while( p != NULL ) {
        if( 0 == strcmp(p->name, name) )
            return p;
        p = p->link;
    }
    return NULL;
}

struct symbol* take_symbol_at(struct symbol_table* table, int index)
{
    if( index >= table->count )
        return NULL;
    struct symbol* p = table->begin;
    while( index > 0 && p != NULL ) {
        p = p->link;
        --index;
    }
    return p;
}

void destroy_symbol_table(struct symbol_table* table)
{
    struct symbol* p = table->begin;
    while( table->begin != NULL ) {
        p = table->begin;
        table->begin = p->link;
        destroy_symbol(p);
    }
}

void print_table(struct symbol_table* table)
{
    struct symbol* p = table->begin;
    while( p != NULL ) {
        // TODO: add branches for expression and function
        printf("%s = \n", p->name);
        p = p->link;
    }
}
